// 1. rust通过所有权机制来管理内存，编译器在编译就会根据所有权规则对内存的使用进行检查

// 2. 堆和栈
// 编辑的时候数据的类型大小是固定的，就是分配在栈上的
// 编辑的时候数据类型大小不固定，就是分配在堆上的

// 3. 作用域：就是在{}这个范围，超过这个{}离开了当前作用域
// 4. String内存回收
// 5. 移动
// 6. clone
// 7. 栈上数据拷贝
// 8. 函数和作用域

fn main() {
    // 作用域的例子
    let x: i32 = 1;
    {
        let y: i32 = 1;
        println!("x = {x}");
        println!("y = {y}");
    }
    //println!("y = {y}"); // 这里会报错，因为y已经离开了作用域，此时在调用y是无效的

    {
        let mut s1 = String::from("hello");
        s1.push_str("! word!");
        println!("s1 = {s1}"); //String类型离开作用域的时候会调用drop方法

        // 5. 移动
        let s2 = s1;
        println!("s2 = {s2}");
        //println!("s1再次调用{s1}") // 这里会报错，但是没有离开作用域，s1移动给s2后，s1就无效了，所以会报错

        // clone方法，相当于深拷贝
        let s3 = s2.clone();
        println!("s3 = {s3}");
        println!("s2 = {s2}");
    }
    // 栈上的数据拷贝 copy 就是实现copy 这个特征（trait）
    let a = 1;
    let b = a;
    println!("a = {a}");
    println!("b = {b}"); // 为什么不报错呢：因为编辑的时候数据的类型大小是固定的，就是分配在栈上的
    // 常用地具有copy 特征有：所有整型、浮点型、布尔类型、字符（char）、元祖


    println!("Hello, world!");
}
